home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / INFO / XFDISK.ZIP / PREPARE.A86 < prev    next >
Text File  |  1991-08-28  |  36KB  |  859 lines

  1. ;==============================================================================
  2. ;
  3. ; PREPARE  version 1.00  August 28, 1991
  4. ; Fixed Disk Preparation and Partitioning Software.
  5. ; Copyright (C) 1991 Dennis W. Person.  All rights reserved.
  6. ;
  7. ;==============================================================================
  8. ;
  9. ; written by:  Dennis W. Person
  10. ;              6828 Devonshire Drive
  11. ;              Canton, MI  48187-2613
  12. ;
  13. ;==============================================================================
  14. ;
  15. ; This program will clear ALL sectors on a fixed disk by writing the value V to
  16. ; ALL sectors.  You CANNOT recover any data on your fixed disk once it has been
  17. ; cleared.  BEFORE running this program, make sure you have a current backup of
  18. ; your fixed disk.
  19. ;
  20. ; Command:  PREPARE [/?│[/1│/2] [/R│/P] [/V:vvv] [/C:cccc] [/H:hhh] [/S:ss]]
  21. ;
  22. ; Options:  /?  display this help
  23. ;           /1  prepare 1st fixed disk
  24. ;           /2  prepare 2nd fixed disk
  25. ;           /R  read disk only (use to test disk)
  26. ;           /P  prepare fixed disk by writing V (default of 0) to all sectors
  27. ;           /V  specify decimal value [vvv] to use for preparing fixed disk
  28. ;           /C  specify maximum cylinder [cccc] (0..1023)
  29. ;           /H  specify maximum head [hhh] (0..255)
  30. ;           /S  specify maximum sectors per track [ss] (1..63)
  31. ;
  32. ; The options [/1│/2] and [/R│/P] must be specified to execute the command.
  33. ;==============================================================================
  34.  
  35. DOS_VER   EQU 5    ; program intended for DOS 5.00 or greater
  36.  
  37. IBUFSIZE  EQU 1    ; maximum number of character allowed in input buffer
  38.  
  39. VDECDIGS  EQU 3    ; maximum number of decimal digits for value
  40. CDECDIGS  EQU 4    ; maximum number of decimal digits for cylinders
  41. HDECDIGS  EQU 3    ; maximum number of decimal digits for heads
  42. SDECDIGS  EQU 2    ; maximum number of decimal digits for sectors
  43.  
  44. MAX_VAL   EQU 255  ; maximum value allowed for preparing disk
  45. MAX_CYL   EQU 1023 ; maximum cylinder number allowed by DOS
  46. MAX_HDS   EQU 255  ; maximum head number allowed by DOS
  47. MAX_SEC   EQU 63   ; maximum sector number allowed by DOS
  48.  
  49. BPS       EQU 512  ; bytes per sector (default defined by DOS)
  50.  
  51. NONE      EQU 0FFFFh ; define value to indicate no user selected disk parameter
  52.  
  53. BS        EQU 08h  ; ASCII backspace
  54. CR        EQU 0Dh  ; ASCII carriage return
  55. LF        EQU 0Ah  ; ASCII line feed
  56. EOM       EQU "$"  ; ASCII character defining end of message
  57.  
  58. UPCHRMSK  EQU 0DFh ; mask to convert lower case to upper case
  59.  
  60. DRIVE_1   EQU "1"  ; drive character for 1st fixed disk drive
  61. DRIVE_2   EQU "2"  ; drive character for 2nd fixed disk drive
  62.  
  63. DRV_1_NO  EQU 080h ; drive number for 1st fixed disk drive
  64. DRV_2_NO  EQU 081h ; drive number for 2nd fixed disk drive
  65.  
  66. RD_CODE   EQU 02h  ; disk service function code to read from disk drive
  67. WR_CODE   EQU 03h  ; disk service function code to write to disk drive
  68.  
  69. CTRLBINT  EQU 01Bh ; CTRL-BREAK INT number
  70. CTRLCINT  EQU 023h ; CTRL-C INT number
  71.  
  72. BUFFER    EQU 080h ; address of command line buffer
  73.  
  74. ;==============================================================================
  75.  
  76.           ORG 0100h     ; set beginning address for program
  77.  
  78. MAIN:     MOV AX,CS     ; initialize segment registers
  79.           MOV DS,AX     ; except those related to the stack,
  80.           MOV ES,AX     ; i.e., SS, and the stack pointer, SP
  81.  
  82.           MOV DX,SIGNON  ; display sign-on message
  83.           CALL PUTMSG
  84.  
  85.           MOV AH,030h    ; get function code and
  86.           INT 021h       ; get DOS version number
  87.  
  88.           CMP AL,DOS_VER ; check if DOS version appropriate
  89.           JGE CONTINUE   ; continue if DOS version appropriate
  90.                          ; otherwise, . . .
  91.           MOV DX,DOSMSG  ; get address of exit message
  92.           MOV AL,081h    ; set exit error code
  93.           JMP EXIT
  94.  
  95. CONTINUE: CALL PARSE     ; parse options on command line
  96.           JC SHOWHELP    ; CF set if error occurred
  97.  
  98.           CMP BYTE PTR [DRIVE_NO],DRV_1_NO ; check if user entered /1
  99.           JZ HAVEDRV                       ; otherwise user MUST enter /2
  100.  
  101.           CMP BYTE PTR [DRIVE_NO],DRV_2_NO ; check if user entered /2
  102.           JZ HAVEDRV                       ; show HELP if no /1 or /2
  103.  
  104. SHOWHELP: MOV DX,HELPMSG ; get address of exit message
  105.           MOV AL,0FFh    ; set exit error code
  106.           JMP EXIT
  107.  
  108. HAVEDRV:  CALL GETPARAM  ; get parameters for fixed disk drive selected by user
  109.           JNC CHK_VAL    ; CF set if no fixed disk drive installed
  110.  
  111.           MOV DX,NODRVMSG ; get address of exit message
  112.           MOV AL,082h     ; set exit error code
  113.           JMP EXIT
  114.  
  115. CHK_VAL:  MOV SI,USR_VAL   ; get address of user specified value
  116.           MOV AX,[SI]      ; get value specified by user and
  117.           CMP AX,MAX_VAL   ; and check that value ok
  118.           JLE SET_CYL
  119.                            ; otherwise, . . .
  120.           MOV DX,BAD_VAL   ; get address of exit message
  121.           MOV AL,088h      ; set exit error code
  122.           JMP EXIT
  123.  
  124. SET_CYL:  MOV BX,NONE      ; prepare to check for user parameters
  125.           MOV SI,USR_CYL   ; get address of user parameter for cylinders
  126.           CMP [SI],BX      ; check if user entered value for cylinders
  127.           JZ SET_HDS       ; if no value on command line
  128.  
  129.           MOV AX,[SI]      ; get value specified by user and
  130.           MOV [CYL_MAX],AX ; put in location for max. cylinders
  131.           CMP AX,MAX_CYL   ; check if more than maximum allowed by DOS
  132.           JLE SET_HDS      ; continue if value entered by user ok
  133.                            ; otherwise, . . .
  134.           MOV DX,BAD_CYL   ; get address of exit message
  135.           MOV AL,085h      ; set exit error code
  136.           JMP EXIT
  137.  
  138. SET_HDS:  MOV SI,USR_HDS   ; get address of user parameter for heads
  139.           CMP [SI],BX      ; check if user entered value for heads
  140.           JZ SET_SEC       ; if no value on command line
  141.  
  142.           MOV AX,[SI]      ; get value specified by user and
  143.           MOV [HDS_MAX],AX ; put in location for max. heads
  144.           CMP AX,MAX_HDS   ; check if more than maximum allowed by DOS
  145.           JLE SET_SEC      ; continue if value entered by user ok
  146.                            ; otherwise, . . .
  147.           MOV DX,BAD_HDS   ; get address of exit message
  148.           MOV AL,086h      ; set exit error code
  149.           JMP EXIT
  150.  
  151. SET_SEC:  MOV SI,USR_SEC   ; get address of user parameter for sectors
  152.           CMP [SI],BX      ; check if user entered value for sectors
  153.           JZ WARNUSR       ; if no value on command line
  154.  
  155.           MOV AX,[SI]      ; get value specified by user and
  156.           MOV [SECTORS],AX ; put in location for sectors per track
  157.           OR AX,0          ; check that user specfied at least 1 sector
  158.           JZ BAD_USR       ; if zero, display error message
  159.                            ; otherwise, . . .
  160.           CMP AX,MAX_SEC   ; check if more than maximum allowed by DOS
  161.           JLE WARNUSR      ; continue if value entered by user ok
  162.                            ; otherwise, . . .
  163. BAD_USR:  MOV DX,BAD_SEC   ; get address of exit message
  164.           MOV AL,087h      ; set exit error code
  165.           JMP EXIT
  166.  
  167. WARNUSR:  MOV DX,WARNMSG                 ; get address of write warning message
  168.           CMP BYTE PTR [RW_FUNC],WR_CODE ; check if going to clear disk
  169.           JZ SHOWSTAT                    ; and display write warning message
  170.                                          ; otherwise, . . .
  171.           MOV DX,READMSG                 ; get address of read warning message
  172.           CMP BYTE PTR [RW_FUNC],RD_CODE ; check if going to read disk
  173.           JZ SHOWSTAT                    ; and display write warning message
  174.                                          ; otherwise, . . .
  175.           MOV DX,BAD_CODE                ; get address of exit message
  176.           MOV AL,083h                    ; get exit error code
  177.           JMP EXIT                       ; user MUST specify /R or /P
  178.  
  179. SHOWSTAT: CALL PUTMSG     ; display warning regarding disk READ or WRITE
  180.  
  181. QUERYUSR: MOV DX,ASKYN    ; get address of message and
  182.           CALL PROMPTER   ; prompt for user"s response
  183.           JZ QUERYUSR     ; if no response, prompt again
  184.                           ; otherwise, . . .
  185.           OR CL,0         ; if more than 1 character entered,
  186.           JNZ QUERYUSR    ; go prompt user again
  187.                           ; otherwise, . . .
  188.           AND AL,UPCHRMSK ; mask response to upper case
  189.                           ; and check for valid response
  190.           CMP AL,"Y"      ; check user"s response for Y
  191.           JZ BEGIN        ; if Y, begin disk preparation
  192.                           ; otherwise, . . .
  193.           CMP AL,"N"      ; check user"s response for N
  194.           JNZ QUERYUSR    ; if not N, then prompt again
  195.                           ; otherwise, . . .
  196.           MOV DX,QUITMSG  ; get address of exit message
  197.           MOV AL,084h     ; set exit error code
  198.           JMP EXIT        ; quit program
  199.  
  200. BEGIN:    MOV DX,RETURN   ; return cursor and
  201.           CALL PUTMSG     ; move cursor down two lines
  202.  
  203.           MOV AL,CTRLBINT ; get INT number for CONTROL-BREAK
  204.           MOV DI,CTRL_BRK ; get location to save old INT vector
  205.           CALL SETINT     ; set CONTROL-BREAK interrupt vector
  206.  
  207.           MOV AL,CTRLCINT ; get INT number for CONTROL-C
  208.           MOV DI,CTRL_C   ; get location to save old INT vector
  209.           CALL SETINT     ; set CONTROL-BREAK interrupt vector
  210.  
  211.           MOV CX,02000h   ; set parameters to turn cursor off
  212.           CALL CURSOR     ; call DOS video service handler
  213.  
  214. FILL_DTA: MOV AX,BPS      ; calculate number of bytes required for disk buffer
  215.           MUL BX          ; by multiplying number of sectors by 512 bytes
  216.           MOV SI,AX       ; save result in SI
  217.  
  218.           MOV AX,CS       ; use 64K above current code segment as buffer area
  219.           ADD AX,01000h   ; addd 64K to current CS
  220.           MOV ES,AX       ; ES used for disk buffer segment
  221.  
  222.           MOV DI,USR_VAL    ; get address of value for preparing fixed disk
  223.           MOV AL,[DI]       ; prepare to clear disk buffer
  224.                             ; and . . .
  225. FILL:     ES: MOV [SI-1],AL ; go do it
  226.           DEC SI
  227.           JNZ FILL
  228.  
  229.           MOV AH,0 ; start with disk system in reset condition
  230.           INT 013h
  231.  
  232.           MOV BX,[CYL_MAX]  ; start at maximum disk cylinder
  233.  
  234. NEXTCYL:  MOV [CYLINDER],BX ; get next cylinder to prepare
  235.           MOV CL,CDECDIGS   ; get number of decimal digits to display cylinder
  236.           MOV DI,CYL_NUM    ; get location to put decimal digits
  237.           CALL BIN2DEC      ; and insert current cylinder into message
  238.  
  239.           MOV BX,[HDS_MAX]  ; start at maximum disk head
  240.  
  241. NEXTHEAD: MOV [HEAD],BX     ; get next head to prepare
  242.           MOV CL,HDECDIGS   ; get number of decimal digits to display head
  243.           MOV DI,HD_NUM     ; get location to put decimal digits
  244.           CALL BIN2DEC      ; and insert current head into message
  245.  
  246.           MOV DX,DISKMSG    ; get address of message
  247.           CALL PUTMSG       ; show user current head and cylinder
  248.  
  249.           MOV SI,3          ; initialize number of tries for accessing disk
  250.  
  251. TRYAGAIN: CALL CLRKEY       ; clear keyboard buffer
  252.  
  253.           CMP BYTE PTR [STOP],1 ; check if user pressed BREAK
  254.           JNZ DODISK
  255.  
  256.           MOV DX,BREAKMSG ; get address of exit message
  257.           MOV AL,1        ; set exit error code
  258.           JMP EXIT
  259.                               ; setup to registers to do disk function
  260. DODISK:   MOV DH,[HEAD]       ; get current head
  261.           MOV DL,[DRIVE_NO]   ; get drive number [80] or [81]
  262.           MOV CH,[CYLINDER]   ; get low-order byte for cylinder
  263.           MOV CL,6            ; prepare to get upper 2-bits for cylinder
  264.           MOV AL,[CYLINDER+1] ; get high-order byte for cylinder
  265.           SHL AL,CL           ; shift lower 2-bits of AL to upper 2-bits of AL
  266.           MOV CL,AL           ; copy upper 2-bits to CL for proper setup
  267.           OR CL,1             ; start with first sector on track (lower 6-bits)
  268.           XOR BX,BX           ; get address of disk buffer ES:BX
  269.           MOV AL,[SECTORS]    ; get number of sector to prepare
  270.           MOV AH,[RW_FUNC]    ; get READ or WRITE function code
  271.           INT 013h            ; call BIOS routine to do disk function
  272.           JNC EXITLOOP        ; CF clear if no error
  273.                               ; otherwise, . . .
  274.           MOV AH,0            ; get function code to reset disk system
  275.           INT 013h            ; call BIOS routine to reset disk system
  276.           DEC SI              ; decrement counter for number of tries
  277.           JNZ TRYAGAIN        ; and try again if counter > 0
  278.                               ; otherwise, . . .
  279.           MOV DX,ERRMSG       ; get address of exit message
  280.           MOV AL,3            ; set exit error code
  281.           JMP EXIT
  282.  
  283. EXITLOOP: MOV BX,[HEAD]       ; get current head
  284.           DEC BX              ; prepare to do next head
  285.           JGE NEXTHEAD        ; and go do next head until complete
  286.  
  287.           MOV BX,[CYLINDER]   ; get current cylinder
  288.           DEC BX              ; prepare to do next cylinder
  289.           JGE NEXTCYL         ; and go do next cylinder until complete
  290.  
  291.           MOV DX,DONEMSG      ; get address of exit message
  292.           MOV AL,0            ; set exit error code to indicate sucess
  293.  
  294. EXIT:     PUSH AX      ; save exit error code
  295.           PUSH DX      ; save address of exit message
  296.  
  297.           CMP AL,080h  ; check exit error code
  298.           JNC EXIT2    ; codes greater than 07F did not change BREAK vectors
  299.  
  300.           MOV CX,0607h ; set scan line parameters for DOS cursor
  301.           CALL CURSOR  ; restore DOS cursor
  302.  
  303.           MOV AL,CTRLCINT ; get INT number for CONTROL-C
  304.           MOV SI,CTRL_C   ; get location of old INT vector
  305.           CALL RESETINT   ; reset CONTROL-C interrupt vector
  306.  
  307.           MOV AL,CTRLBINT ; get INT number for CONTROL-BREAK
  308.           MOV SI,CTRL_BRK ; get location of old INT vector
  309.           CALL RESETINT   ; reset CONTROL-BREAK interrupt vector
  310.  
  311. EXIT2:    MOV AH,0 ; exit with disk system in reset condition
  312.           INT 013h
  313.  
  314.           POP DX      ; get address of exit message
  315.           CALL PUTMSG ; and display exit message for user
  316.  
  317.           POP AX      ; get exit error code
  318.           MOV AH,04Ch ; get function code to exit program
  319.           INT 021h    ; exit program with return code
  320.  
  321. ;------------------------------------------------------------------------------
  322. ; subroutine to clear keyboard buffer
  323. ;------------------------------------------------------------------------------
  324.  
  325. CLRKEY:   MOV AH,1 ; get function code to check keyboard
  326.           INT 016h ; call BIOS routine to check keyboard
  327.           JZ NOKEY ; if no key pressed, exit
  328.                    ; otherwise, . . .
  329.           MOV AH,0 ; get function code to read keyboard buffer
  330.           INT 016h ; call DOS function to read keyboard buffer
  331.  
  332. NOKEY:    RET
  333.  
  334. ;------------------------------------------------------------------------------
  335. ; subroutine to reset INT number address
  336. ;
  337. ;   on entry:  AL  contains INT number
  338. ;              SI  contains location of saved INT vector
  339. ;------------------------------------------------------------------------------
  340.  
  341. RESETINT: MOV DX,[SI]   ; put INT vector in DS:DX
  342.           MOV DS,[SI+2]
  343.           MOV AH,025h   ; get function code
  344.           INT 021h      ; restore INT vector
  345.  
  346.           MOV AX,CS
  347.           MOV DS,AX     ; restore DS register
  348.           RET
  349.  
  350. ;------------------------------------------------------------------------------
  351. ; subroutine to save vector for INT number and set new vector
  352. ;
  353. ;   on entry:  AL  contains INT number
  354. ;              DI  contains location to save old INT vector
  355. ;           DS:DX  contains new INT vector
  356. ;------------------------------------------------------------------------------
  357.  
  358. SETINT:   PUSH AX
  359.           MOV AH,035h     ; set function code and interrupt number
  360.           INT 021h        ; get interrupt vector for CONTROL-BREAK
  361.  
  362.           MOV [DI],BX     ; save interrupt vector ES:BX
  363.           MOV [DI+2],ES
  364.  
  365.           MOV DX,BREAK    ; get address of CONTROL-BREAK handler DS:DX
  366.           POP AX          ; get INT number for CONTROL-BREAK
  367.  
  368.           MOV AH,025h     ; set function code
  369.           INT 021h        ; set interrupt vector for CONTROL-BREAK
  370.           RET
  371.  
  372. ;------------------------------------------------------------------------------
  373. ; subroutine to set cursor start and end scan lines
  374. ;
  375. ;   on entry:  CH  contains start scan line
  376. ;              CL  contains end scan line
  377. ;------------------------------------------------------------------------------
  378.  
  379. CURSOR:   MOV AH,1 ; select function
  380.           INT 010h ; call DOS video service handler
  381.           RET
  382.  
  383. ;------------------------------------------------------------------------------
  384. ; subroutine to get parameters for fixed disk drive
  385. ;
  386. ;   on exit:  AX  contains number of cylinders          [0 .. 1023]
  387. ;             BL  contains number of sectors per track  [0 ... 255]
  388. ;             CL  contains number of heads (sides)      [0 .... 63]
  389. ;             DL  contains number of fixed disk drives  [1 or 2]
  390. ;
  391. ;             values of register are invalid if carry flag set
  392. ;
  393. ;             CF  flag set if no fixed disk drives
  394. ;                      clear if at least 1 fixed disk drive
  395. ;------------------------------------------------------------------------------
  396.  
  397. GETPARAM: MOV AH,8          ; get function code to check drive parameters
  398.           MOV DL,[DRIVE_NO] ; get drive number for fixed disk drive
  399.           INT 013h          ; call BIOS routine to get drive parameters
  400.           JC NODRIVE        ; CF set if no fixed disks installed
  401.           
  402.           MOV AH,[DRIVE_NO] ; get drive selected by user
  403.           AND AH,1          ; mask to check if 2nd fixed disk selected
  404.           XOR AH,DL         ; determine if 2nd fixed disk exists
  405.           JZ NODRIVE        ; ZF set if no 2nd fixed disk installed
  406.  
  407.           XOR BH,BH         ; process fixed disk drive parameters
  408.           MOV AH,CL         ; that were returned by the INT 013h call
  409.           MOV BL,CL         ; as follows:
  410.           AND AH,0C0h       ;
  411.           AND BL,03Fh       ; DL number of drives
  412.           MOV CL,6          ; DH number of heads
  413.           SHR AH,CL         ; CL lower order byte for cylinders
  414.           MOV AL,CH         ; CH upper 2-bits:  high order 2-bits for cylinder
  415.           XOR CX,CX         ; CH lower 6-bits:  sectors per track
  416.           MOV CL,DH         ;
  417.  
  418.           MOV [CYL_MAX],AX  ; save fixed disk drive parameters
  419.           MOV [SECTORS],BX
  420.           MOV [HDS_MAX],CX
  421.           MOV [NUM_DRVS],DL
  422.  
  423.           CLC ; clear CF if no errors with fixed disk drive selected by user
  424.           RET
  425.  
  426. NODRIVE:  STC ; set CF if errors with fixed disk drive selected by user
  427.           RET
  428.  
  429. ;------------------------------------------------------------------------------
  430. ; subroutine to display message for user
  431. ;
  432. ;   on entry:  DX  contains address of message
  433. ;------------------------------------------------------------------------------
  434.  
  435. PUTMSG:   MOV AH,9 ; get function code to display message
  436.           INT 021h ; call DOS routine to display message
  437.           RET
  438.  
  439. ;------------------------------------------------------------------------------
  440. ; subroutine to convert decimal ASCII characters to 16-bit binary value
  441. ;
  442. ;   on entry:  CL  contains count of characters in command buffer
  443. ;              CH  contains maximum number of characters to process
  444. ;              SI  contains address of decimal ASCII characters less 1
  445. ;              DI  contains address to put binary value
  446. ;
  447. ;   on exit:  AX  contains binary value
  448. ;             BH  contains number of decimal characters in number
  449. ;             CF  flag clear if valid value
  450. ;                      set if error occured
  451. ;
  452. ;   MUL instruction uses the DX register for the high order 16-bits of
  453. ;   the 32-bit result, so do NOT use the DX register in this subroutine.
  454. ;------------------------------------------------------------------------------
  455.  
  456. DEC2BIN:  XOR AX,AX   ; initialize registers to be used
  457.           XOR BX,BX
  458.           MOV BP,10
  459.  
  460. CHKBUFF:  OR CL,0     ; check for more characters in buffer
  461.           JZ CHKFOR1  ; exit appropriately if no more characters
  462.                       ; otherwise, . . .
  463.           INC SI      ; increment pointer to character buffer
  464.           DEC CL      ; decrement character count
  465.           MOV BL,[SI] ; and fetch character
  466.  
  467.           CMP BL," "  ; if character is a space,
  468.           JZ CHKFOR1  ; exit appropriately
  469.                       ;
  470. CHKOPT:   CMP BL,"/"  ; if beginning of another option,
  471.           JZ RESETBUF ; exit appropriately
  472.  
  473. CHKDIG:   CMP BL,"0"  ; if character is less than "0"
  474.           JL BADDIGIT ; exit with error
  475.                       ; OR . . .
  476.           CMP BL,"9"  ; if character is greater than "9"
  477.           JG BADDIGIT ; exit with error
  478.                       ; otherwise, . . .
  479.           MUL BP      ; multiply current value by 10 to shift decimal value
  480.           AND BL,0Fh  ; convert ASCII decimal to BCD value
  481.           ADD AL,BL   ; and value to lower order byte of AX
  482.           ADC AH,0    ; and carry to high order byte of AX
  483.           INC BH      ; increment counter for number of characters
  484.           DEC CH      ; check if more characters allowed
  485.           JNZ CHKBUFF ; and go get the next one
  486.                       ; otherwise, . . .
  487. D2BDONE:  MOV [DI],AX ; save binary value
  488.           CLC         ; clear CF to indicate valid value
  489.           RET
  490.  
  491. RESETBUF: INC CL      ; beginning of another option "/", so
  492.           DEC SI      ; restore buffer pointer and count
  493.  
  494. CHKFOR1:  OR BH,0     ; check that at least 1 decimal digit was entered
  495.           JNZ D2BDONE ; and exit with valid value
  496.                       ; otherwise, . . .
  497. BADDIGIT: STC         ; set CF to indicate error
  498.           RET
  499.  
  500. ;------------------------------------------------------------------------------
  501. ; subroutine to convert 16-binary value to decimal ASCII characters
  502. ;
  503. ;   on entry:  BX  contains binary value
  504. ;              CL  contains number of decimal digits
  505. ;              DI  contains address to put decimal ASCII characters
  506. ;
  507. ;   DIV instruction uses the DX register for the high order 16-bits of
  508. ;   the 32-bit dividend, so initialize the DX register before dividing.
  509. ;------------------------------------------------------------------------------
  510.  
  511. BIN2DEC:  MOV DL," "
  512.           MOV CH,CL
  513.           MOV SI,DI
  514.  
  515. INIDIGS:  MOV [SI],DL
  516.           INC SI
  517.           DEC CH
  518.           JNZ INIDIGS
  519.  
  520.           MOV BP,10
  521.           DEC SI
  522.           DEC CL
  523.           JZ ONESDIG
  524.  
  525.           MOV AX,1
  526.           MOV CH,CL
  527.  
  528. SETDIG:   MUL BP
  529.           DEC CH
  530.           JNZ SETDIG
  531.  
  532. NEXTDIG:  MOV CH,-1
  533.  
  534. DIVBY10X: INC CH
  535.           SUB BX,AX
  536.           JNC DIVBY10X
  537.  
  538.           ADD BX,AX
  539.           CALL DEC2ASC
  540.  
  541.           XOR DX,DX
  542.           DIV BP
  543.           DEC CL
  544.           JNZ NEXTDIG
  545.  
  546. ONESDIG:  MOV CH,BL
  547.  
  548. DEC2ASC:  ADD CH,"0"
  549.           CMP CH,"0"
  550.           JNZ PUTDIGIT
  551.  
  552.           MOV DL," "
  553.           CMP DL,[DI-1]
  554.           JNZ PUTDIGIT
  555.  
  556.           CMP DI,SI
  557.           JZ PUTDIGIT
  558.  
  559.           MOV CH,DL
  560.           DEC DI
  561.           DEC SI
  562.  
  563. PUTDIGIT: MOV [DI],CH
  564.           INC DI
  565.           RET
  566.  
  567. ;------------------------------------------------------------------------------
  568. ; subroutine to prompt the user and pre-process the user"s input
  569. ;
  570. ;   on entry:  DX  contains address of prompt to be displayed
  571. ;------------------------------------------------------------------------------
  572.  
  573. PROMPTER: CALL PUTMSG           ; display prompt on console
  574.                                 ;
  575.           MOV CL,IBUFSIZE+1     ; get maximum size of input buffer
  576.           MOV SI,USRIBUFF       ; get address of user input buffer
  577.           MOV [SI],CL           ; and put size into buffer
  578.                                 ;
  579.           ADD SI,2              ; point to first charcter in buffer
  580.                                 ; and . . .
  581. FILLBUFR: MOV BYTE PTR [SI]," " ; put space into buffer
  582.           INC SI                ; increment buffer pointer
  583.           DEC CL                ; decrement buffer counter
  584.           JNZ FILLBUFR          ; loop until end of buffer
  585.                                 ;
  586.           MOV DX,USRIBUFF       ; get address of buffer DS:DX
  587.           MOV AL,0Ah            ; get function code to input string
  588.           MOV AH,0Ch            ; get function code to clear keyboard buffer
  589.           INT 021h              ; go execute DOS function to read keyboard
  590.                                 ;
  591.           MOV SI,USRIBUFF+1     ; point to buffer count
  592.           MOV CL,[SI]           ; get count for number of characters
  593.  
  594. GET1CHAR: OR CL,0               ; check if count is zero
  595.           JZ ENDPRMPT           ; if no user response, return with Z set
  596.                                 ; otherwise, . . .
  597.           DEC CL                ; decrement buffer character count
  598.           INC SI                ; point to next character in buffer
  599.           MOV AL,[SI]           ; and retrieve character to AL
  600.                                 ;
  601.           CMP AL," "            ; check for space character
  602.           JZ GET1CHAR           ; if space, check for another character
  603.                                 ; otherwise, . . .
  604. ENDPRMPT: RET                   ; return with character in AL
  605.  
  606. ;------------------------------------------------------------------------------
  607. ; subroutine to process the command line options
  608. ;
  609. ;   valid options:  /?       display command help
  610. ;                   /1       select 1st fixed disk
  611. ;                   /2       select 2nd fixed disk
  612. ;                   /P       prepare fixed disk by writing 0 to all sectors
  613. ;                   /R       read disk only {used for testing disk}
  614. ;                   /V:vvv   specify decimal value [vvv] for preparing disk
  615. ;                   /C:cccc  specify maximum cylinder [cccc]
  616. ;                   /H:hhh   specify maximum head [hhh]
  617. ;                   /S:ss    specify maximum sectors [ss]
  618. ;
  619. ;   on exit:  CF  flag set if error on command line
  620. ;                      clear if no errors on command line
  621. ;
  622. ;------------------------------------------------------------------------------
  623.  
  624. PARSE:    MOV SI,BUFFER     ; get address of command buffer
  625.           MOV CL,[SI]       ; get number of characters in buffer
  626.  
  627. NEXTCHAR: CALL GET1CHAR     ; get character from buffer
  628.           JZ COMERR         ; exit with CF set if no characters in buffer
  629.  
  630.           CMP AL,"/"        ; check for option prefix character
  631.           JNZ COMERR        ; exit with CF set if character NOT "/"
  632.  
  633.           CALL GET1CHAR     ; get next next character from buffer
  634.           JZ COMERR         ; exit with CF set if no characters in buffer
  635.  
  636. OPT0:     CMP AL,"?"        ; check if user is requesting HELP
  637.           JZ COMERR         ; exit with CF set if user needs HELP
  638.  
  639. OPT1:     CMP AL,DRIVE_1    ; check if user selected 1st fixed disk
  640.           JNZ OPT2
  641.                             ; and . . .
  642.           MOV AH,DRV_1_NO   ; prepare to set drive number for 1st fixed disk
  643.           JMP SETDRIVE
  644.  
  645. OPT2:     CMP AL,DRIVE_2    ; check if user selected 2nd fixed disk
  646.           JNZ OPT3
  647.                             ; and . . .
  648.           MOV AH,DRV_2_NO   ; prepare to set drive number for 2nd fixed disk
  649.  
  650. SETDRIVE: MOV [WARN_DRV],AL ; put drive character into warning message
  651.           MOV [DONE_DRV],AL ; put drive character into completion message
  652.           MOV [DRIVE_NO],AH ; set drive number for fixed disk selected by user
  653.           JMP GETNEXT       ; go continue to parse command line
  654.  
  655. OPT3:     AND AL,UPCHRMSK   ; convert lowercase to uppercase
  656.           CMP AL,"R"        ; check if user selected READ option
  657.           JNZ OPT4
  658.                             ; and . . .
  659.           MOV AL,RD_CODE    ; prepare to setup for disk READ
  660.           JMP SET_RW
  661.  
  662. OPT4:     CMP AL,"P"        ; check if user selected PREPARE option
  663.           JNZ OPT5
  664.                             ; and . . .
  665.           MOV AL,WR_CODE    ; prepare to setup for disk WRITE
  666.  
  667. SET_RW:   MOV [RW_FUNC],AL  ; set function code to READ or WRITE disk
  668.  
  669. GETNEXT:  OR CL,CL          ; if more characters entered on command line
  670.           JNZ NEXTCHAR      ; go process additional options entered by user
  671.  
  672.           CLC ; exit with CF clear if no errors on command line
  673.           RET
  674.  
  675. COMERR:   STC ; exit with CF set if errors on command line
  676.           RET
  677.  
  678. OPT5:     MOV AH,AL         ; prepare to check for additional options
  679.           CALL GET1CHAR     ; get next character from buffer
  680.           JZ COMERR         ; exit with CF set if no characters in buffer
  681.  
  682.           CMP AX,"V:"       ; check if user selecting value for preparing disk
  683.           JNZ OPT6
  684.  
  685.           MOV CH,VDECDIGS   ; get max. number of decimal digits for value
  686.           MOV DI,USR_VAL    ; get location to put user value
  687.           JMP GETNUM        ; continue processing to get binary value
  688.  
  689. OPT6:     CMP AX,"C:"       ; check if user selecting value to prepare disk
  690.           JNZ OPT7
  691.  
  692.           MOV CH,CDECDIGS   ; get max. number of decimal digits for cylinders
  693.           MOV DI,USR_CYL    ; get location to put user number of cylinders
  694.           JMP GETNUM        ; continue processing to get binary value
  695.  
  696. OPT7:     CMP AX,"H:"       ; check if user selecting number of heads
  697.           JNZ OPT8
  698.  
  699.           MOV CH,HDECDIGS   ; get max. number of decimal digits for heads
  700.           MOV DI,USR_HDS    ; get location to put user number of heads
  701.           JMP GETNUM        ; continue processing to get binary value
  702.  
  703. OPT8:     CMP AX,"S:"       ; check if user selecting number of sectors
  704.           JNZ COMERR        ; exit if CF set if valid option NOT entered
  705.  
  706.           MOV CH,SDECDIGS   ; get max. number of decimal digits for sectors
  707.           MOV DI,USR_SEC    ; get location to put user number of sectors
  708.  
  709. GETNUM:   CALL DEC2BIN      ; convert ASCII decimal number to binary value
  710.           JNC GETNEXT       ; if no error, go parse additional options
  711.                             ; otherwise, . . .
  712.           RET               ; exit with CF set if bad number
  713.                             
  714. ;------------------------------------------------------------------------------
  715. ; subroutine to handle CONTROL-BREAK and CONTROL-C
  716. ;------------------------------------------------------------------------------
  717.  
  718. BREAK:    CS: MOV BYTE PTR [STOP],1 ; simply set STOP if user presses BREAK
  719.           IRET
  720.  
  721. ;------------------------------------------------------------------------------
  722.  
  723. USRIBUFF: DB IBUFSIZE+3 DUP ? ; input buffer for user query
  724.  
  725. CTRL_C:   DW 2 DUP ? ; address of CONTROL-C handler
  726. CTRL_BRK: DW 2 DUP ? ; address of CONTROL-BREAK handler
  727. STOP      DB 0       ; set to 1 if user presses CONTROL-C or CONTROL-BREAK
  728.  
  729. HEAD      DW ? ; counter for heads
  730. CYLINDER  DW ? ; counter for cylinders
  731.  
  732. CYL_MAX   DW ? ; maximum number of cylinders MINUS 1
  733. HDS_MAX   DW ? ; maximum number of heads MINUS 1
  734. SECTORS   DW ? ; sectors per track
  735.  
  736. USR_VAL:  DW 0    ; user selected value to use for preparing fixed disk
  737. USR_CYL:  DW NONE ; maximum cylinder number entered by user on command line
  738. USR_HDS:  DW NONE ; maximum head number entered by user on command line
  739. USR_SEC:  DW NONE ; sectors per track entered by user on command line
  740.  
  741. NUM_DRVS  DB ? ; number of fixed disk drives
  742. DRIVE_NO  DB 0 ; fixed disk drive number
  743. RW_FUNC   DB 0 ; function code to read from or write to disk drive
  744.  
  745. DISKMSG:  DB "Head:  "
  746. HD_NUM:   DB HDECDIGS DUP ?
  747.           DB "    "
  748.           DB "Cylinder:  "
  749. CYL_NUM:  DB CDECDIGS DUP ?
  750.           DB CR
  751.           DB EOM
  752.  
  753. SIGNON:   DB CR,LF
  754.           DB "PREPARE  version 1.00  August 28, 1991",CR,LF
  755.           DB "Fixed Disk Preparation and Partitioning Software.",CR,LF
  756.           DB "Copyright (C) 1991 Dennis W. Person.  All rights reserved.",CR,LF
  757.           DB EOM
  758.  
  759. READMSG:  DB CR,LF
  760.           DB "Fixed disk will be READ for test purposes only.",CR,LF
  761.           DB EOM
  762.  
  763. WARNMSG:  DB CR,LF
  764.           DB "═════════════════════                    ═════════════════════"
  765.           DB CR,LF
  766.           DB " W A R N I N G ! ! !                      W A R N I N G ! ! ! "
  767.           DB CR,LF
  768.           DB "═════════════════════                    ═════════════════════"
  769.           DB CR,LF,LF
  770.           DB "ALL DATA ON FIXED DISK DRIVE ["
  771. WARN_DRV  DB ?
  772.           DB "] WILL BE LOST IF YOU CONTINUE.",CR,LF
  773.           DB EOM
  774.  
  775. ASKYN:    DB CR,
  776.           DB "Proceed with fixed disk preparation [Y│N] ?  ",BS
  777.           DB EOM
  778.  
  779. RETURN:   DB CR,LF,LF,EOM
  780.  
  781. BAD_VAL:  DB CR,LF
  782.           DB "ERROR [88]:  Value used to prepare fixed disk must be less than 256.",CR,LF
  783.           DB EOM
  784.  
  785. BAD_SEC:  DB CR,LF
  786.           DB "ERROR [87]:  Number of sectors MUST be at least 1 but less than 64.",CR,LF
  787.           DB EOM
  788.  
  789. BAD_HDS:  DB CR,LF
  790.           DB "ERROR [86]:  Number of heads MUST be less than 256.",CR,LF
  791.           DB EOM
  792.  
  793. BAD_CYL:  DB CR,LF
  794.           DB "ERROR [85]:  Number of cylinders MUST be less than 1024.",CR,LF
  795.           DB EOM
  796.  
  797. QUITMSG:  DB CR,LF,LF
  798.           DB "ERROR [84]:  Fixed disk preparation cancelled.",CR,LF
  799.           DB EOM
  800.  
  801. BAD_CODE: DB CR,LF
  802.           DB "ERROR [83]:  You MUST also use either /R or /P on the command line.",CR,LF
  803.           DB EOM
  804.  
  805. NODRVMSG: DB CR,LF
  806.           DB "ERROR [82]:  No fixed disk drive exists.",CR,LF
  807.           DB EOM
  808.  
  809. DOSMSG:   DB CR,LF
  810.           DB "ERROR [81]:  Incorrect DOS version.  DOS 5.00 or greater needed."
  811.           DB CR,LF
  812.           DB EOM
  813.  
  814. ERRMSG:   DB CR,LF,LF
  815.           DB "ERROR [2]:  Unable to complete fixed disk preparation.",CR,LF
  816.           DB "            Either disk is bad in area shown above OR",CR,LF
  817.           DB "            you entered an invalid drive parameter.",CR,LF
  818.           DB EOM
  819.  
  820. BREAKMSG: DB CR,LF,LF
  821.           DB "ERROR [1]:  Fixed disk preparation cancelled by BREAK."
  822.           DB CR,LF
  823.           DB EOM
  824.  
  825. DONEMSG:  DB CR,LF,LF
  826.           DB "Fixed disk preparation for DRIVE ["
  827. DONE_DRV  DB ?
  828.           DB "] completed sucessfully.",CR,LF
  829.           DB EOM
  830.  
  831. HELPMSG:  DB CR,LF
  832.           DB "This program will clear ALL sectors on a fixed disk by writing the value V to",CR,LF
  833.           DB "ALL sectors.  You CANNOT recover any data on your fixed disk once it has been",CR,LF
  834.           DB "cleared.  BEFORE running this program, make sure you have a current backup of",CR,LF
  835.           DB "your fixed disk."
  836.           DB CR,LF,LF
  837.           DB "Command:  PREPARE [/?│[/1│/2] [/R│/P] [/V:vvv] [/C:cccc] [/H:hhh] [/S:ss]]"
  838.           DB CR,LF,LF
  839.           DB "Options:  /?  display this help",CR,LF
  840.           DB "          /1  prepare 1st fixed disk",CR,LF
  841.           DB "          /2  prepare 2nd fixed disk",CR,LF
  842.           DB "          /R  read fixed disk only (use to test disk)",CR,LF
  843.           DB "          /P  prepare fixed disk by writing V (default of 0) to all sectors",CR,LF
  844.           DB "          /V  specify decimal value [vvv] to use for preparing fixed disk",CR,LF
  845.           DB "          /C  specify maximum cylinder [cccc] (0..1023)",CR,LF
  846.           DB "          /H  specify maximum head [hhh] (0..255)",CR,LF
  847.           DB "          /S  specify maximum sectors per track [ss] (1..63)"
  848.           DB CR,LF,LF
  849.           DB "The options [/1│/2] and [/R│/P] must be specified to execute the command.",CR,LF
  850.           DB EOM
  851.  
  852. ;==============================================================================
  853. ;
  854. ; PREPARE  version 1.00  August 28, 1991
  855. ; Fixed Disk Preparation and Partitioning Software.
  856. ; Copyright (C) 1991 Dennis W. Person.  All rights reserved.
  857. ;
  858. ;==============================================================================
  859.